package com.hn.sanya.zzht.config.Interceptor;

import com.auth0.jwt.internal.org.bouncycastle.asn1.ocsp.ResponseData;
import com.hn.sanya.zzht.entity.User;
import com.hn.sanya.zzht.model.ResponseStatus;
import com.hn.sanya.zzht.util.jwtUtil;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.Set;

/**
 * 自定义拦截器
 * @author ZSX
 *
 */

@Component
public class LoginInterceptor implements HandlerInterceptor {


	private static Set<String> excludeUrls = new HashSet<String>(); // 不需要拦截的资源

	{
		excludeUrls.add("/user/getTableData");
	}


	/**
	 * 这个方法的主要作用是用于清理资源的，当然这个方法也只能在当前这个Interceptor的preHandle方法的返回值为true时才会执行。
	 */
	@Override
	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
		// TODO Auto-generated method stub

	}

	/**
	 * 在Controller的方法调用之后执行
	 */
	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
			throws Exception {
		// TODO Auto-generated method stub

	}

	/** 
     * preHandle方法是进行处理器拦截用的，顾名思义，该方法将在Controller处理之前进行调用，
     * SpringMVC中的Interceptor拦截器是链式的，可以同时存在多个Interceptor，
     * 然后SpringMVC会根据声明的前后顺序一个接一个的执行，而且所有的Interceptor中的preHandle方法都会在Controller方法调用之前调用。
     * SpringMVC的这种Interceptor链式结构也是可以进行中断的，这种中断方式是令preHandle的返 
     * 回值为false，当preHandle的返回值为false的时候整个请求就结束了。 
     */
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {

		//获取请求url
		String requestURI = request.getRequestURI();
		String contextPath = request.getContextPath();
		String url = requestURI.substring(contextPath.length() + 1);
		String method=request.getMethod();
		request.setAttribute("url", url);


		//判断session用户是否未登录
		response.setCharacterEncoding("utf-8"); //此处是前台将token和loginId 放到了headers里面，后来来获取并处理
		String requestToken =request.getHeader("X-Token");
		String token= (String) request.getSession().getAttribute("token");
		ResponseStatus responseStatus = ResponseStatus.ok();

		//判断是放行url
		if ("".equals(url) || validateUrls(url)&&!"OPTIONS".equals(method)) {
			return true;
		}

		if (requestToken==null||token==null) {
			//未登录返回标识码
			responseMessage(response, response.getWriter(), responseStatus.noLogin());
			return false;
		}else{

			User userToken = jwtUtil.unsign(token, User.class); //解密token后的loginId与用户传来的loginId不一致，一般都是token过期

			if(null != requestToken && null != token) {
				if(requestToken == token) {
					return true;
				} else{
					responseStatus = ResponseStatus.forbidden();
					responseMessage(response, response.getWriter(), responseStatus);
					return false;
				}
			} else {
				responseStatus = ResponseStatus.forbidden();
				responseMessage(response, response.getWriter(), responseStatus);
				return false;
			}
		}
	}

	//请求不通过，返回错误信息给客户端
	private void responseMessage(HttpServletResponse response, PrintWriter out, ResponseStatus responseStatus) {

		JSONObject json = JSONObject.fromObject(responseStatus);
		out.print(json.toString());
		out.flush();
		out.close();
	}

	/**
	 * 验证url是否在允许访问的url列表里面，即未登录既可以访问的url
	 * @param url
	 * @return
	 */
	private boolean validateUrls(String url) {
		url = "/" + url;

		if (excludeUrls.contains(url)) {
			return true;
		}
		for (String string : excludeUrls) {
			if (string.endsWith("*") &&
					url.indexOf(string.substring(0, string.length() - 1)) != -1) {
				return true;
			}
		}
		return false;
	}
}
